/*
 * 文件名：Page.java
 * 版权：Copyright by will_awoke
 * 描述：
 * 修改人：lyh
 * 修改时间：2013-10-10
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package com.qbgs.base;


import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;

import com.qbgs.constant.GlobalConstant;
import com.qbgs.util.ConvertKeyUtil;


/**
 * 分页实体 （支持mysql）
 * @author lyh
 * @version 2013-10-10
 * @see Page
 * @since
 */
public class Page implements Serializable
{
    /**
     * 序列号<br>
     */
    private static final long serialVersionUID = -2554565760258955645L;

    /**
     * 日志
     */
    private static final Logger logger = Logger.getLogger(Page.class);

    /**
     * 每页显示的记录数
     */
    private int numPerPage;

    /**
     * 总页数
     */
    private int totalPages;

    /**
     * 当前页码
     */
    private int currentPage;

    /**
     * 记录起始行数
     */
    private int startIndex;

    /**
     * 记录结束行数
     */
    private int lastIndex;

    /**
     * 记录总数 （命名必须为total 对应easyui分页）
     */
    private int total = 0;

    /**
     * 结果集存放List （命名必须为rows 对应easyui分页）
     */
    private List<Map<String, Object>> rows =  new LinkedList<Map<String, Object>>();

    /**
     * 构造函数
     * @param sql sql语句，支持含通配符?替换
     * @param queryParamVals sql 查询参数集合
     * @param currentPage 当前页码
     * @param numPerPage 每页显示记录数
     * @param jdbcTemplate JdbcTemplate实例
     * @param isKeyLower 是否将key转为小写  ture：小写  false：大写
     */
    public Page(String sql, List<Object> queryParamVals, int currentPage, int numPerPage,
                JdbcTemplate jdbcTemplate, boolean isKeyLower)
    {
        if (jdbcTemplate == null)
        {
            throw new IllegalArgumentException("jdbcTemplate is null , pls initialize ... ");
        }
        if (StringUtils.isBlank(sql))
        {
            throw new IllegalArgumentException("sql is blank , pls initialize ... ");
        }
        //如果每页显示记录数<=0 则修改为默认的10
        if (numPerPage <= 0)
        {
            numPerPage = GlobalConstant.QUERY_PER_PAGE_DEF;
        }
        //查询参数值数组
        Object[] queryParamValArray = null;
        if (!CollectionUtils.isEmpty(queryParamVals))
        {
            queryParamValArray = queryParamVals.toArray();
        }
        //设置每页显示记录数
        setNumPerPage(numPerPage);

        //设置当前页数
        setCurrentPage(currentPage);

        //计算总记录数SQL
        StringBuffer totalSQL = new StringBuffer(" select count(1) from ( ");
        totalSQL.append(sql);
        //totalSQL.append(" ) "); //for oracle
        totalSQL.append(" ) as total");//every derived table must have its own alias in mysql

        //总记录数
        setTotal(jdbcTemplate.queryForInt(totalSQL.toString(), queryParamValArray));

        //计算总页数
        setTotalPages();

        //计算起始行数
        setStartIndex();

        //计算结束行数
        setLastIndex();

        //拼装分页语句
        //for oracle
        /*StringBuffer paginationSQL = new StringBuffer(" select * from ( ");
        paginationSQL.append(" select row_limit.*,rownum rownum_ from ( ");
        paginationSQL.append(sql);
        paginationSQL.append("　) row_limit where rownum <= " + lastIndex);
        paginationSQL.append(" ) where　rownum_ > " + startIndex);*/
        
        //for mysql
        StringBuffer paginationSQL = new StringBuffer(sql);
        paginationSQL.append(" limit ").append(startIndex).append(',').append(numPerPage);

        //isKeyLower = ture 则转为小写  否则 key依旧保持原有的大写
        if (isKeyLower)
        {
            //装入结果集（key转为小写）
            setRows(ConvertKeyUtil.listKeyToLower(jdbcTemplate.queryForList(
                paginationSQL.toString(), queryParamValArray)));
        }
        else
        {
            setRows(jdbcTemplate.queryForList(paginationSQL.toString(), queryParamValArray));
        }

        //日志打印查询参数
        logger.debug("Executing prepared SQL query paras: " + queryParamVals);
    }

    /**
     * 根据总记录数和每页显示记录数 计算总页数
     *    
     * @see
     */
    private void setTotalPages()
    {
        if (total % numPerPage == 0)
        {
            this.totalPages = total / numPerPage;
        }
        else
        {
            this.totalPages = (total / numPerPage) + 1;
        }
    }

    /**
     * 根据当前页和每页显示记录条数 计算记录开始行数
     *    
     * @see
     */
    private void setStartIndex()
    {
        this.startIndex = (currentPage - 1) * numPerPage;
    }

    /**
     * 计算记录结束行数
     *    
     * @see
     */
    private void setLastIndex()
    {
        if (total < numPerPage)
        {
            this.lastIndex = total;
        }
        else if ((total % numPerPage == 0)
                 || (total % numPerPage != 0 && currentPage < totalPages))
        {
            this.lastIndex = currentPage * numPerPage;
        }
        else if (total % numPerPage != 0 && currentPage == totalPages)
        {
            this.lastIndex = total;
        }
    }

    //setter and getter
    public int getCurrentPage()
    {
        return currentPage;
    }

    public void setCurrentPage(int currentPage)
    {
        this.currentPage = currentPage;
    }

    public int getNumPerPage()
    {
        return numPerPage;
    }

    public void setNumPerPage(int numPerPage)
    {
        this.numPerPage = numPerPage;
    }

    public List<Map<String, Object>> getRows()
    {
        return rows;
    }

    public void setRows(List<Map<String, Object>> rows)
    {
        this.rows = rows;
    }

    public int getTotalPages()
    {
        return totalPages;
    }

    public int getTotal()
    {
        return total;
    }

    public void setTotal(int total)
    {
        this.total = total;
    }

    public int getStartIndex()
    {
        return startIndex;
    }

    public int getLastIndex()
    {
        return lastIndex;
    }

}
